package com.zlzlib.libnetty.msg;


import com.zlzlib.libnetty.listener.NettyClientInterface;
import com.zlzlib.libnetty.listener.NettyDataListener;
import com.zlzlib.libnetty.util.Util;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by zlz on 2019/11/18.
 * 消息发送超时自动发送管理器
 */
public class MsgTimeoutTimerManager<T> {

    private final Map<String, MsgTimeoutTimer<T>> mMsgTimeoutMap = new ConcurrentHashMap<>();
    private final NettyClientInterface<T> imsClient;// ims客户端

    public MsgTimeoutTimerManager(NettyClientInterface<T> imsClient) {
        this.imsClient = imsClient;
    }

    /**
     * 添加消息到发送超时管理器
     *
     * @param msg 超时消息
     */
    public void add(T msg) {
        if (imsClient.getDataListener().isDataEmpty(msg)) {
            return;
        }
        NettyDataListener<T> dataListener = imsClient.getDataListener();
        // 握手消息、心跳消息、客户端返回的状态报告消息，不用重发。
        if (dataListener.isHandshakeMsg(msg) || dataListener.isHeartbeatMsg(msg) || dataListener.isReceivedReportMsg(msg)) {
            return;
        }
        String msgId = imsClient.getDataListener().getMsgId(msg);
        if (null != msgId && !mMsgTimeoutMap.containsKey(msgId)) {
            MsgTimeoutTimer<T> timer = new MsgTimeoutTimer<>(imsClient, msg);
            mMsgTimeoutMap.put(msgId, timer);
        }
        Util.logInfo("添加消息超发送超时管理器，message=" + msg + "\t当前管理器消息数：" + mMsgTimeoutMap.size());
    }

    /**
     * 从发送超时管理器中移除消息，并停止定时器
     *
     * @param msgId 消息id
     */
    public void remove(String msgId) {
        if (msgId == null || msgId.isEmpty()) {
            return;
        }
        MsgTimeoutTimer<T> timer = mMsgTimeoutMap.remove(msgId);
        T msg = null;
        if (timer != null) {
            msg = timer.getMsg();
            timer.cancel();
            timer = null;
        }
        Util.logInfo("从发送消息管理器移除消息，message=" + msg);
    }

    /**
     * 重连成功回调，重连并握手成功时，重发消息发送超时管理器中所有的消息
     */
    public synchronized void onResetConnected() {
        for (Map.Entry<String, MsgTimeoutTimer<T>> stringMsgTimeoutTimerEntry : mMsgTimeoutMap.entrySet()) {
            stringMsgTimeoutTimerEntry.getValue().sendMsg();
        }
    }

}
